home *** CD-ROM | disk | FTP | other *** search
- // DiskChanger.c
- // 28 Jul 1996 10:34:27
-
- #ifndef BACKUP_INCLUDE
- #include "IncludeAll.c"
- #endif
- #include "Backup.h"
- #include "Backup_proto.h"
- #include "BackupStrings.h"
- #include "DiskChanger.h"
-
- #define d(x) ;
-
- #define POLL_TAPE
-
-
- static struct IORequest *DCOpenDevice(char *name, int unit, ULONG IORSize, ULONG Flags);
- static void DCCloseDevice(struct IORequest *req);
- static void SendDC(struct DiskChangeInfo *dci, unsigned short Class);
- static void __asm __saveds DiskChangerInt(register __a1 struct DiskChangeInfo *dci);
- static ULONG DCTestDiskChange(struct DiskChangeInfo *dci, BOOL First);
- static ULONG DCTestNewDisk(struct DiskChangeInfo *dci);
- static enum TestDiskResult DCCheckLabel(struct DiskChangeInfo *dci);
- static void AbortTimerIO(struct DiskChangeInfo *dci);
- static void SetDiskStatus(struct DiskChangeInfo *dci, enum DskStat NewState);
- static void SendDCRx(struct DiskChangeInfo *dci, unsigned short Class);
- static BOOL CheckDCTxPort(struct DiskChangeInfo *dci);
-
-
- // aus ProcStart.asm
- extern APTR __far DiskChangerSeg; // SegList für CreateProc
-
- // aus Backup.c
- extern struct Window *aktWindow;
- extern char StartZeit[8];
- extern struct BackupDevInfo globDrvDat; // globale Disk-Parameter
- extern struct DiskFlags __far *Disks;
- extern struct BackupOptions myOptions; // Einstellungen für die aktuelle Sicherung
-
- // aus Backup_Window.c
- extern unsigned long DiskChangeMaske;
-
-
- // Lokale Konstanten
- #ifdef POLL_TAPE
- static const DC_Poll = 2500; // Zeit zwischen 2 Polls für Band in ms
- #endif
-
- static const DC_Timeout = 1300; // Wartezeit für neue Disk in ms
- // vergrößert wegen Komplikationen mit dem mfm.device
- static const DC_StackSize = 8192; // Stackgröße für DiskChanger-Task
-
-
- // Lokale Variablen
- static struct SignalSemaphore StartDCSema; // Semaphore zur Verriegelung bei Prozeß-Start
- static short StartDCSemaInit = FALSE;
-
- static InfoLineHandle PilHandle = NULL;
-
-
- struct DiskChangeInfo *StartDiskChanger(short UnitNr,
- BOOL FirstDisk, short NextDiskNo)
- {
- struct DiskChangeInfo *dci;
- struct Process *myproc;
- struct MsgPort *myport;
- struct DiskFlags *Dsk = &Disks[UnitNr];
-
- ASSERT_VALID(Dsk);
-
- if (globDrvDat.BlockSize == 0)
- {
- alarm(GetString(MSG_ZEROBLOCKSIZE), __FUNC__);
- return FALSE;
- }
-
- dci = calloc(sizeof(struct DiskChangeInfo), 1);
- if (dci == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "dci", sizeof(struct DiskChangeInfo));
- return NULL;
- }
-
- if (!StartDCSemaInit)
- {
- InitSemaphore(&StartDCSema);
- StartDCSemaInit = TRUE;
- }
-
- InitSemaphore(&dci->Sema);
-
- dci->DCRxPort = CreateMsgPort();
- if (NULL == dci->DCRxPort)
- {
- alarm(GetString(MSG_CREATEPORT_FAILED), __FUNC__, "DCRxPort");
- return FALSE;
- }
-
- memcpy(dci->StartZeit, StartZeit, sizeof(dci->StartZeit));
- dci->NextDiskNr = NextDiskNo;
-
- dci->DiskBlockSize = globDrvDat.BlockSize;
- dci->DiskBufMemType = globDrvDat.BufMemType;
-
- dci->UnitNr = UnitNr;
-
- dci->TDName = Dsk->DeviceName;
- dci->TDUnit = Dsk->Unit;
- dci->TDFlags = Dsk->DrvDat.Flags;
- dci->DOSName = Dsk->DOSName;
-
- dci->DrvDat = &Dsk->DrvDat;
- dci->Env = Dsk->Env;
- dci->DiskStatus = CheckingDisk;
-
- if (Dsk->TapeReq)
- {
- dci->isTape = TRUE;
- dci->TapeReq = AllocVec(sizeof(struct TapeIO), Dsk->DrvDat.BufMemType);
- if (dci->TapeReq == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "dci->TapeReq", sizeof(struct TapeIO));
- return NULL;
- }
- *dci->TapeReq = *Dsk->TapeReq;
- }
-
- dci->Pos = FirstDisk ? 1 : 2;
-
- sprintf(dci->ProcessName, "Backup_DiskChange_%s", Dsk->DOSName);
-
- ObtainSemaphore(&StartDCSema); // Prozeß blockieren bis <dci> eingetragen
- myport = CreateProc(dci->ProcessName, 0L, MKBADDR(&DiskChangerSeg), DC_StackSize);
-
- if (myport)
- {
- struct DCMessage *Msg;
- ULONG off;
-
- off = offsetof(struct Process, pr_MsgPort);
- myproc = (struct Process *) ((char *) myport - off);
- myproc->pr_Task.tc_UserData = (APTR) dci;
- ReleaseSemaphore(&StartDCSema);
-
- // auf Init.-Quittung warten
- WaitPort(dci->DCRxPort);
- Msg = (struct DCMessage *) GetMsg(dci->DCRxPort); // Quittung holen
- if (Msg)
- {
- dci->Result = DC_INITOK == Msg->dc_Class ? DCOK : BAD;
- d(kprintf(__FUNC__ "/%ld: Msg=%08lx Class=%lx\n", __LINE__, Msg, Msg->dc_Class);)
- free(Msg);
- }
- else
- dci->Result = BAD;
- }
- else
- {
- ReleaseSemaphore(&StartDCSema);
- alarm(GetString(MSG_CREATEPROC_FAILED), __FUNC__, dci->ProcessName);
- dci->Result = BAD; // CreateProc versagt !
- }
-
- if (DCOK == dci->Result)
- {
- DiskChangeMaske |= 1 << dci->DCTxPort->mp_SigBit;
- }
- else
- {
- free(dci);
- dci = NULL;
- }
-
- return dci;
- }
-
-
- void EndDiskChanger(struct DiskChangeInfo *dci)
- {
- ASSERT_VALID(dci);
-
- if (dci && dci->DiskChangerTask)
- {
- if (dci->DCRxPort && dci->DCTxPort)
- {
- struct DCMessage *Msg;
- unsigned short Class;
-
- SendDC(dci, DC_SHUTDOWN);
-
- do {
- // warten auf Ende-Quittung
- WaitPort(dci->DCRxPort);
- Msg = (struct DCMessage *) GetMsg(dci->DCRxPort);
- if (Msg)
- {
- d(kprintf(__FUNC__ "/%ld: Msg=%08lx Class=%lx\n", __LINE__, Msg, Msg->dc_Class);)
- Class = Msg->dc_Class;
- free(Msg);
- }
- else
- Class = 0;
- } while (Class != DC_DOWN);
- }
-
- dci->DiskChangerTask = NULL;
- if (dci->TapeReq)
- {
- FreeVec(dci->TapeReq);
- dci->TapeReq = NULL;
- }
-
- if (dci->DCRxPort)
- {
- DeleteMsgPort(dci->DCRxPort);
- dci->DCRxPort = NULL;
- }
-
- free(dci);
- }
- }
-
-
- // Message an DiskChanger-Prozeß senden
- static void SendDC(struct DiskChangeInfo *dci, unsigned short Class)
- {
- struct DCMessage *Msg;
-
- Msg = malloc(sizeof(struct DCMessage));
- if (Msg)
- {
- Msg->dc_Msg.mn_ReplyPort = dci->DCRxPort;
- Msg->dc_Msg.mn_Length = sizeof(struct DCMessage);
- Msg->dc_Class = Class;
-
- d(kprintf(__FUNC__ "/%ld: send %lx\n", __LINE__, (long) Class);)
- PutMsg(dci->DCTxPort, (struct Message *) Msg);
-
- WaitPort(dci->DCRxPort); // Warten auf Reply
- Msg = (struct DCMessage *) GetMsg(dci->DCRxPort); // Reply-Port leeren
- free(Msg);
- }
- }
-
-
- // ======================================================
- // ab hier läuft der Code als eigener Prozeß !
-
- // main() des DiskChangers
- void __saveds BackupDiskChanger(void)
- {
- struct DiskChangeInfo *dci;
- struct Task *myTask;
- struct Device *dev;
- ULONG Signals, Signals2;
- BYTE DiskChangeSignal;
- BOOL DCRunning;
-
- ObtainSemaphore(&StartDCSema); // Warten bis dci eingetragen ist
- myTask = FindTask(NULL);
- dci = (struct DiskChangeInfo *) myTask->tc_UserData;
- ReleaseSemaphore(&StartDCSema);
-
- ObtainSemaphore(&dci->Sema);
-
- dci->DiskChangerTask = myTask;
- DiskChangeSignal = AllocSignal(-1);
- dci->DiskChangeMask = 1 << DiskChangeSignal;
-
- do {
- dci->DCTxPort = CreateMsgPort();
- if (dci->DCTxPort == NULL)
- {
- ReleaseSemaphore(&dci->Sema);
- SendDCRx(dci, DC_INITBAD);
- alarm(GetString(MSG_CREATEPORT_FAILED), __FUNC__, "DCTxPort");
- break;
- }
-
- dci->DCTxPortMask = 1 << dci->DCTxPort->mp_SigBit;
-
- dci->DiskChangeInt.is_Node.ln_Succ = NULL;
- dci->DiskChangeInt.is_Node.ln_Pred = NULL;
- dci->DiskChangeInt.is_Node.ln_Type = NT_INTERRUPT;
- dci->DiskChangeInt.is_Node.ln_Pri = 0;
- dci->DiskChangeInt.is_Node.ln_Name = NULL;
- dci->DiskChangeInt.is_Data = dci;
- dci->DiskChangeInt.is_Code = (void (*)()) DiskChangerInt;
-
- dci->DiskIOReq = (struct IOExtTD *) DCOpenDevice(dci->TDName,
- dci->TDUnit, sizeof(struct IOExtTD), dci->TDFlags);
-
- if (NULL == dci->DiskIOReq)
- {
- // Init. Mißerfolg melden
- ReleaseSemaphore(&dci->Sema);
- SendDCRx(dci, DC_INITBAD);
-
- break;
- }
- dci->ChangeIOReq = *(dci->DiskIOReq);
-
- dci->TimerIOReq = (struct timerequest *) DCOpenDevice((STRPTR) TIMERNAME,
- UNIT_VBLANK, sizeof(struct timerequest), 0);
- if (dci->TimerIOReq == NULL)
- {
- // Init. Mißerfolg melden
- DCCloseDevice((struct IORequest *) dci->DiskIOReq);
- SendDCRx(dci, DC_INITBAD);
- ReleaseSemaphore(&dci->Sema);
-
- break;
- }
- dci->TimerMask = 1 << dci->TimerIOReq->tr_node.io_Message.mn_ReplyPort->mp_SigBit;
- dci->TimerInUse = 0;
-
- #ifdef POLL_TAPE
- if (!dci->isTape)
- #endif
- {
- // DiskChange-Interrupt einhängen
- dci->ChangeIOReq.iotd_Req.io_Command = TD_ADDCHANGEINT;
- dci->ChangeIOReq.iotd_Req.io_Flags = 0;
- dci->ChangeIOReq.iotd_Req.io_Length = sizeof(struct Interrupt);
- dci->ChangeIOReq.iotd_Req.io_Data = (APTR) &dci->DiskChangeInt;
- SendIO((struct IORequest *) &dci->ChangeIOReq);
- }
-
- // Init. Ok melden
- SendDCRx(dci, DC_INITOK);
-
- if (dci->isTape)
- {
- dci->TapeReq->Req = dci->DiskIOReq;
- TapeInitProperties(dci->TapeReq);
- }
-
- Signals2 = DCTestDiskChange(dci, TRUE); // zu Beginn Disk-Zustand festhalten
-
- ReleaseSemaphore(&dci->Sema);
- // Init. fertig
-
- #ifdef POLL_TAPE
- if (dci->isTape)
- {
- dci->TimerIOReq->tr_time.tv_secs = 0;
- dci->TimerIOReq->tr_time.tv_micro = 1000 * DC_Poll;
- dci->TimerIOReq->tr_node.io_Command = TR_ADDREQUEST;
- SendIO((struct IORequest *) dci->TimerIOReq);
- dci->TimerInUse = 1;
- d(kprintf(__FUNC__ "/%ld: %s: Band-Timer erstmals gestartet\n", __LINE__, dci->DOSName);)
- }
- #endif
- DCRunning = TRUE;
-
- do {
- if (Signals2)
- {
- Signals = Signals2;
- Signals2 = 0L;
- }
- else
- Signals = Wait(dci->DiskChangeMask | dci->DCTxPortMask | dci->TimerMask);
-
-
- if (Signals & dci->DCTxPortMask)
- {
- DCRunning &= CheckDCTxPort(dci);
- }
- #ifdef POLL_TAPE
- if (dci->isTape)
- {
- if (Signals & dci->TimerMask)
- {
- short NoDisk, Empty;
-
- WaitIO((struct IORequest *) dci->TimerIOReq);
-
- NoDisk = TapeChangeState(dci->TapeReq);
- Empty = dci->DiskStatus == EmptyDrive ||
- dci->DiskStatus == WaitingForDisk ||
- dci->DiskStatus == CheckingDisk;
-
- if ((!NoDisk && Empty)
- || (NoDisk && !Empty))
- {
- Signals2 |= DCTestDiskChange(dci, FALSE);
- }
-
- dci->TimerIOReq->tr_time.tv_secs = 0;
- dci->TimerIOReq->tr_time.tv_micro = 1000 * DC_Poll;
- dci->TimerIOReq->tr_node.io_Command = TR_ADDREQUEST;
- SendIO((struct IORequest *) dci->TimerIOReq);
- dci->TimerInUse = 1;
- d(kprintf(__FUNC__ "/%ld: %s: Band-Timer neu gestartet\n", __LINE__, dci->DOSName);)
- }
- }
- else
- #endif
- {
- if (Signals & dci->TimerMask)
- {
- d(kprintf(__FUNC__ "/%ld: %s: Timer abgelaufen\n", __LINE__, dci->DOSName);)
- dci->TimerInUse = 0;
- Signals2 |= DCTestNewDisk(dci);
- }
-
- if (Signals & dci->DiskChangeMask)
- {
- // Diskwechsel wurde erkannt
- Signals2 |= DCTestDiskChange(dci, FALSE);
- }
- }
- } while (DCRunning);
-
- // Prozeß wird beendet
-
- #ifdef POLL_TAPE
- if (!dci->isTape)
- #endif
- {
- // DiskChange-Interrupt wieder entfernen !
- dev = dci->ChangeIOReq.iotd_Req.io_Device;
- if (dev->dd_Library.lib_Version >= 38)
- {
- dci->ChangeIOReq.iotd_Req.io_Command = TD_REMCHANGEINT;
- dci->ChangeIOReq.iotd_Req.io_Flags = IOF_QUICK;
- dci->ChangeIOReq.iotd_Req.io_Length = sizeof(struct Interrupt);
- dci->ChangeIOReq.iotd_Req.io_Data = (APTR) &dci->DiskChangeInt;
-
- DoIO((struct IORequest *) &dci->ChangeIOReq);
- }
- else
- {
- Forbid();
- Remove((struct Node *) &dci->ChangeIOReq);
- Permit();
- }
- }
- } while (0);
-
- AbortTimerIO(dci);
- DCCloseDevice((struct IORequest *) dci->TimerIOReq);
- DCCloseDevice((struct IORequest *) dci->DiskIOReq);
-
- ObtainSemaphore(&dci->Sema);
-
- Forbid();
- SendDCRx(dci, DC_DOWN);
- ReleaseSemaphore(&dci->Sema);
-
- FreeSignal(DiskChangeSignal);
-
- if (dci->DCTxPort)
- {
- DeleteMsgPort(dci->DCTxPort);
- dci->DCTxPort = NULL;
- }
- }
-
-
- static struct IORequest *DCOpenDevice(char *name, int unit, ULONG IORSize,
- ULONG Flags)
- {
- int error;
- struct MsgPort *port;
- struct IORequest *req;
-
- ASSERT_VALID(name);
-
- if ((port = CreateMsgPort()) == NULL)
- {
- alarm(GetString(MSG_CREATEPORT_FAILED), __FUNC__, "port");
- return NULL;
- }
-
- req = CreateIORequest(port, IORSize);
- if (req == NULL)
- {
- alarm(GetString(MSG_CREATEEXTIO_FAILED), __FUNC__, "req");
- DeleteMsgPort(port);
- return NULL;
- }
- error = OpenDevice(name, unit, req, Flags);
- if (error)
- {
- alarm(GetString(MSG_ERROR_OPENDEVICE), __FUNC__,
- name, unit, ErrorText(error), error);
- DeleteIORequest(req);
- DeleteMsgPort(port);
-
- return NULL;
- }
-
- return req;
- }
-
-
- static void DCCloseDevice(struct IORequest *req)
- {
- if (req)
- {
- struct MsgPort *Port;
-
- CloseDevice(req);
-
- Port = req->io_Message.mn_ReplyPort;
-
- DeleteIORequest(req);
- DeleteMsgPort(Port);
- }
- }
-
-
- // DiskChange-Interrupt-Routine. Signalisiert dem DiskChanger-Prozeß einen
- // Diskwechsel im Laufwerk.
- static void __asm __saveds DiskChangerInt(register __a1 struct DiskChangeInfo *dci)
- {
- Signal(dci->DiskChangerTask, dci->DiskChangeMask);
- }
-
-
- static ULONG DCTestDiskChange(struct DiskChangeInfo *dci, BOOL First)
- {
- char Message[80];
- ULONG Result = 0L;
-
- ASSERT_VALID(dci);
-
- SetDiskStatus(dci, CheckingDisk);
- dci->ChangeCount = ChangeNum(dci->DiskIOReq);
- AbortTimerIO(dci);
-
- PopInfoLine(&PilHandle);
-
- if (First && dci->isTape)
- TapeTryLoadUnLoad(dci->TapeReq, TRUE);
-
- #ifdef POLL_TAPE
- if (((dci->isTape && TapeChangeState(dci->TapeReq))
- || (!dci->isTape && ChangeState(dci->DiskIOReq))) == 0)
- #else
- if (ChangeState(dci->DiskIOReq) == 0)
- #endif
- {
- // Medium ist vorhanden
-
- #ifdef POLL_TAPE
- if (dci->isTape)
- {
- Result = DCTestNewDisk(dci);
- }
- else
- #endif
- {
- // Diskette ist eingelegt, jetzt Timer starten
- dci->TimerIOReq->tr_time.tv_secs = 0;
- dci->TimerIOReq->tr_time.tv_micro = 1000 * DC_Timeout;
- dci->TimerIOReq->tr_node.io_Command = TR_ADDREQUEST;
- SendIO((struct IORequest *) dci->TimerIOReq);
- dci->TimerInUse = 1;
- }
- }
- else
- {
- // keine Diskette im Laufwerk
- d(kprintf(__FUNC__ "/%ld: %s: Laufwerk leer\n", __LINE__, dci->DOSName);)
-
- stccpy(Message, dci->DOSName, sizeof(Message)-2);
- strcat(Message, ": ");
-
- ObtainSemaphore(&dci->Sema);
- if (dci->DiskStatus != WaitingForDisk)
- {
- DiskText(Message, ~0, ~0, dci->Pos);
-
- if (dci->DiskStatus != DiskInUse)
- SetDiskStatus(dci, EmptyDrive);
- }
- ReleaseSemaphore(&dci->Sema);
- }
-
- return Result;
- }
-
-
- static ULONG DCTestNewDisk(struct DiskChangeInfo *dci)
- {
- char Message[80];
- ULONG Result = 0L;
-
- ASSERT_VALID(dci);
-
- strcpy(Message, dci->DOSName);
- strcat(Message, ": ");
-
- if (!dci->isTape)
- {
- ObtainSemaphore(&dci->Sema);
- Forbid();
- GetDriveParms(dci->DrvDat, dci->Env, dci->DiskIOReq, dci->isTape); // aktuelle Parameter holen
- if (globDrvDat.isPreliminary)
- {
- // globale Diskparameter endgültig eintragen
- globDrvDat = *dci->DrvDat;
- globDrvDat.isPreliminary = FALSE;
- }
- else if (CheckDriveParms(dci->DrvDat, &globDrvDat))
- {
- // Disk-Parameter haben sich verändert !!
- if (dci->DiskStatus != WaitingForDisk)
- SetDiskStatus(dci, DiskObsolete);
- strcat(Message, GetString(MSG_WRONG_DISK_TYPE));
-
- PopInfoLine(&PilHandle);
- PilHandle = PushInfoLine(Message);
-
- Permit();
- ReleaseSemaphore(&dci->Sema);
-
- return 0l;
- }
-
- Permit();
- ReleaseSemaphore(&dci->Sema);
- }
-
- if (dci->isTape && TapeChangeState(dci->TapeReq))
- return 0;
-
- if ((dci->isTape && TapeProtStatus(dci->TapeReq))
- || (!dci->isTape && ProtStatus(dci->DiskIOReq)))
- {
- // Disk ist schreibgeschützt
- strcat(Message, dci->isTape ? GetString(MSG_TAPE1) : GetString(MSG_DISK1));
- strcat(Message, GetString(MSG_IS_WRITEPROTECTED));
-
- SignalUnIconifyMainWindow();
-
- PopInfoLine(&PilHandle);
- PilHandle = PushInfoLine(Message);
-
- if (dci->isTape)
- {
- // schreibgeschütztes Band auswerfen
- TapeTryLoadUnLoad(dci->TapeReq, FALSE);
- }
- }
- else
- {
- switch (DCCheckLabel(dci))
- {
- case DOSDISK:
- d(kprintf(__FUNC__ "/%ld: %s: DOS-Disk erkannt\n", __LINE__, dci->DOSName);)
- if (myOptions.bo_WarnDosDisk)
- {
- SignalUnIconifyMainWindow();
- if ( yesnoWindow(aktWindow, dci->DiskChangeMask | dci->DCTxPortMask,
- &Result, GetString(MSG_USE_DOSDISK_Q),
- dci->DOSName) != *GetString(MSG_YES_SHORT) )
- {
- // DOS-Disk NICHT verwenden
- break;
- }
- }
- // hier weiter mit OK !!!
- case UNREADABLE:
- case OK:
- d(kprintf(__FUNC__ "/%ld: %s: Disk Ok\n", __LINE__, dci->DOSName);)
- if (dci->isTape)
- {
- char Msg2[80];
-
- sprintf(Msg2, "%s: %s #%-3d",
- dci->DOSName,
- GetString(MSG_TAPE_LABEL),
- dci->NextDiskNr);
-
- // "TAPE: Tape #999 abcdefgh"
- sprintf(Message, "%s %*s", Msg2, 63-37 - strlen(Msg2),
- TapeFormat(dci->TapeReq));
-
- // sprintf(Message, "%s: %s #%-3d %-8.8s",
- // dci->DOSName,
- // GetString(MSG_TAPE_LABEL),
- // dci->NextDiskNr,
- // TapeFormat(dci->TapeReq));
- }
- else
- {
- sprintf(Message, "%s: %s #%-3d",
- dci->DOSName,
- GetString(MSG_DISK_LABEL),
- dci->NextDiskNr);
- }
- DiskText(Message, ~0, ~0, dci->Pos);
-
- PopInfoLine(&PilHandle);
-
- d(kprintf(__FUNC__ "/%ld: %s: DiskStatus=%ld\n", __LINE__, dci->DOSName, dci->DiskStatus);)
- if (dci->DiskStatus != DiskInUse)
- {
- ObtainSemaphore(&dci->Sema);
- dci->withQFA = dci->TapeReq && dci->TapeReq->withQFA;
- d(kprintf(__FUNC__ "/%ld\n", __LINE__);)
- SetDiskStatus(dci, DiskOk);
- d(kprintf(__FUNC__ "/%ld\n", __LINE__);)
- ReleaseSemaphore(&dci->Sema);
- }
- break;
-
- case DISKCHANGED:
- d(kprintf(__FUNC__ "/%ld: %s: Disk gewechselt\n", __LINE__, dci->DOSName);)
- ObtainSemaphore(&dci->Sema);
- if (dci->DiskStatus != WaitingForDisk)
- SetDiskStatus(dci, EmptyDrive);
- ReleaseSemaphore(&dci->Sema);
- DiskText(Message, ~0, ~0, dci->Pos);
- break;
-
- case FROMTHISSET:
- d(kprintf(__FUNC__ "/%ld: %s: Disk vom aktuellen Satz\n", __LINE__, dci->DOSName);)
- if (dci->DiskStatus != DiskInUse)
- {
- ObtainSemaphore(&dci->Sema);
- if (dci->DiskStatus != WaitingForDisk)
- SetDiskStatus(dci, DiskObsolete);
- ReleaseSemaphore(&dci->Sema);
- DiskText(Message, ~0, ~0, dci->Pos);
-
- strcat(Message, GetString(dci->isTape ? MSG_TAPE_FROM_THISSET
- : MSG_DISK_FROM_THISSET) );
-
- SignalUnIconifyMainWindow();
-
- PopInfoLine(&PilHandle);
- PilHandle = PushInfoLine(Message);
- }
- break;
-
- case PANIC:
- DiskText(Message, ~0, ~0, dci->Pos);
- d(kprintf(__FUNC__ "/%ld: %s: Panik!!!\n", __LINE__, dci->DOSName);)
- break;
- }
- }
-
- return Result;
- }
-
-
- // Prüft Diskette. Wenn es eine Backup-Disk ist,
- // dürfen Datum und Uhrzeit nicht mit den aktuellen Werten
- // übereinstimmen, sonst wurde eine Diskette vom aktuellen
- // Backup-Satz nochmals verwendet.
- // return OK, wenn Disk Ok
- // return FROMTHISSET, wenn Disk vom aktuellen Satz.
- // return DISKCHANGED, wenn Diskwechsel nicht vollständig
- // return DOSDISK, wenn DOS-Diskette
- static enum TestDiskResult DCCheckLabel(struct DiskChangeInfo *dci)
- {
- struct IOExtTD req;
- short error;
- enum TestDiskResult erg;
- struct DiskLabel *secbuff;
-
- ASSERT_VALID(dci);
-
- if (dci->DiskStatus == DiskInUse)
- return OK;
-
- if (dci->isTape && TapeChangeState(dci->TapeReq))
- return DISKCHANGED;
-
- secbuff = (struct DiskLabel *) AllocVec(dci->DiskBlockSize, dci->DiskBufMemType|MEMF_CLEAR);
- if (secbuff == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "secbuff", dci->DiskBlockSize);
- return PANIC;
- }
- req = *dci->DiskIOReq;
-
- // Disk-Label lesen
-
- if (dci->isTape)
- {
- TapeInitDrive(dci->TapeReq, &Disks[dci->UnitNr]);
-
- if (dci->TapeReq->withQFA)
- {
- error = TapeRewind(dci->TapeReq) ||
- TapeSetDirectoryPartition(dci->TapeReq) ||
- TapeRead(dci->TapeReq, (char *) secbuff, dci->DiskBlockSize) ||
- TapeRewind(dci->TapeReq);
- }
-
- if (!dci->TapeReq->withQFA)
- {
- error = TapeRewind(dci->TapeReq) ||
- TapeRead(dci->TapeReq, (char *) secbuff, dci->DiskBlockSize) ||
- TapeRewind(dci->TapeReq);
- }
- }
- else
- {
- Clear(&req); // zuerst interne Buffer löschen
- error = TRead(&req, 0, (char *) secbuff, dci->DiskBlockSize);
- }
-
- switch (error)
- {
- case 0:
- // Sektor konnte gelesen werden
-
- ObtainSemaphore(&dci->Sema);
- memcpy(&dci->Label, secbuff, sizeof(struct DiskLabel));
- ReleaseSemaphore(&dci->Sema);
-
- if (strcmp(secbuff->Id, DISKID) == 0
- && memcmp(dci->StartZeit, secbuff->BackupZeit, sizeof(dci->StartZeit)) == 0 )
- {
- erg = FROMTHISSET; // Disk ist vom aktuellen Satz
- break;
- }
- else if (strncmp(secbuff->Id, "DOS", 3) == 0)
- {
- erg = DOSDISK; // DOS-Diskette, vor Gebrauch nachfragen
- break;
- }
- else
- erg = OK;
- break;
-
- case TDERR_DiskChanged:
- // keine Disk im Laufwerk
- erg = DISKCHANGED;
- AbortTimerIO(dci);
- break;
-
- default:
- // Sektor 0 nicht lesbar
- erg = UNREADABLE; // Keine Backup-Disk
- break;
- }
-
- FreeVec(secbuff);
- if (!dci->isTape)
- MotorOff(&req);
-
- return erg;
- }
-
-
- static void AbortTimerIO(struct DiskChangeInfo *dci)
- {
- ASSERT_VALID(dci);
-
- if (dci->TimerInUse && dci->TimerIOReq->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE)
- {
- AbortIO((struct IORequest *) dci->TimerIOReq);
- WaitIO((struct IORequest *) dci->TimerIOReq);
- dci->TimerInUse = 0;
- }
- }
-
-
- static void SetDiskStatus(struct DiskChangeInfo *dci, enum DskStat NewState)
- {
- d(kprintf(__FUNC__ "/%ld NewState=%ld\n", __LINE__, NewState);)
- if (NewState != dci->DiskStatus)
- {
- ObtainSemaphore(&dci->Sema);
- dci->DiskStatus = NewState;
- ReleaseSemaphore(&dci->Sema);
- d(kprintf(__FUNC__ "/%ld vor SignalNewDisk()\n", __LINE__);)
- SignalNewDiskOk();
- }
- }
-
-
-
-
- // Message vom DiskChanger-Prozeß an Hauptprozeß senden
- static void SendDCRx(struct DiskChangeInfo *dci, unsigned short Class)
- {
- struct DCMessage *Msg;
-
- Msg = malloc(sizeof(struct DCMessage));
- if (Msg)
- {
- Msg->dc_Msg.mn_ReplyPort = NULL;
- Msg->dc_Msg.mn_Length = sizeof(struct DCMessage);
- Msg->dc_Class = Class;
- d(kprintf(__FUNC__ "/%ld: send %lx\n", __LINE__, (long) Class);)
- PutMsg(dci->DCRxPort, (struct Message *) Msg);
- }
- }
-
-
- // Ergebnis: FALSE wenn abgebrochen werden muß
- static BOOL CheckDCTxPort(struct DiskChangeInfo *dci)
- {
- BOOL DCRunning = TRUE;
- struct DCMessage *Msg;
-
- while (Msg = (struct DCMessage *) GetMsg(dci->DCTxPort))
- {
- unsigned short Class;
-
- Class = Msg->dc_Class;
- ReplyMsg((struct Message *) Msg);
-
- switch (Class)
- {
- case DC_SHUTDOWN:
- d(kprintf(__FUNC__ "/%ld: >>received DC_ABORT oder DC_SHUTDOWN\n", __LINE__);)
- DCRunning = FALSE;
- break;
- default:
- d(kprintf(__FUNC__ "/%ld: >>received unknown %ld\n", __LINE__, (long) Class);)
- break;
- }
- }
-
- return (BOOL) DCRunning;
- }
-
-
-